package ptij.ADSL.pn;

import ptolemy.kernel.*;
import ptolemy.kernel.util.*;
import ptolemy.data.*;
import ptolemy.data.expr.*;
import ptolemy.actor.*;
import ptolemy.domains.pn.kernel.*;

import java.io.*;
import java.util.Vector;

public class BroadBandNetTx extends TypedAtomicActor {
        
    /* Output Ports */
    public TypedIOPort dataTx;
    public TypedIOPort AS0;
    public TypedIOPort LS0;
            
    /* Parameters */    
    public Parameter AS0_Rate;
    public Parameter LS0_Rate;
       
    public Parameter endTime;

    public BroadBandNetTx(TypedCompositeActor container, String name) throws
        NameDuplicationException, IllegalActionException {
        super(container, name);

	LS0 = new TypedIOPort(this, "LS0", false, true);
	LS0.setTypeEquals(ObjectToken.class);
	
        AS0 = new TypedIOPort(this, "AS0", false, true);
	AS0.setTypeEquals(ObjectToken.class);
		
	dataTx = new TypedIOPort(this, "dataTx", false, true);
	dataTx.setTypeEquals(IntToken.class);
	
	AS0_Rate = new Parameter(this, "AS0_Rate", new IntToken(1));
	LS0_Rate = new Parameter(this, "LS0_Rate", new IntToken(1));

	endTime = new Parameter(this, "endTime", new DoubleToken(1.0));
    }

    public void fire() throws IllegalActionException {

        if(_nextFireAS0 == 0) {
            ObjectToken ot = new ObjectToken(new Integer(_data[_counter]));
            AS0.broadcast(ot);
	    dataTx.broadcast(new IntToken(0));

  	    _counter = (_counter + 1) % _data.length;
	    _nextFireAS0 = 1000.0 / _AS0_Rate;
  	}
	
	if(_nextFireLS0 == 0) {	
	    ObjectToken ot = new ObjectToken(new Integer(_data[_counter]));
            LS0.broadcast(ot);
	    dataTx.broadcast(new IntToken(1));
		
   	    _counter = (_counter + 1) % _data.length;
  	    _nextFireLS0 = 1000.0 / _LS0_Rate;
 	}

	_nextFire();	
    }
    
    public void initialize() throws IllegalActionException {
        super.initialize();	

        DoubleToken dt = (DoubleToken) endTime.getToken();
	_endTime = dt.doubleValue();

	IntToken t = (IntToken) AS0_Rate.getToken();
	_AS0_Rate = t.intValue();			
	_nextFireAS0 = 1000.0 / _AS0_Rate;
	
	t = (IntToken) LS0_Rate.getToken();
	_LS0_Rate = t.intValue();
	_nextFireLS0 = 1000.0 / _LS0_Rate;

	try {
            File f = new File("test.dat");
            FileInputStream fi = new FileInputStream(f);
            DataInputStream data = new DataInputStream(fi);
            
	    _data = new int[((int) f.length())/4];
	    for(int i = 0;i < _data.length;i++) {
	        _data[i] = data.readInt();
	    }
	    data.close();
	    fi.close();
	} 
	catch(IOException ex) {
	    System.out.println(ex);
	}
	_counter = 0;
    }

    public boolean postfire() throws IllegalActionException {

        Director d = getDirector();
	if(d.getCurrentTime() >= _endTime) {
	    System.out.println("Bye World");
            d.stopFire();
	}
        return super.postfire();
    }

    private void _nextFire() throws IllegalActionException {
    
        double min = 1000.0;
	boolean sched = false;

        Director d = getDirector();
	
	if(_nextFireAS0 < min) min = _nextFireAS0;	
	if(_nextFireLS0 < min) min = _nextFireLS0;
	
	if(_nextFireAS0 - min == 0) {
	    d.fireAt(this, d.getCurrentTime() + _nextFireAS0);
	    sched = true;
	}
	_nextFireAS0 -= min;

	if((sched == false) && (_nextFireLS0 - min == 0))  {
	    d.fireAt(this, d.getCurrentTime() + _nextFireLS0);
	}

	_nextFireLS0 -= min;
    }   
    
    private int _AS0_Rate;
    private int _LS0_Rate;
    
    private double _nextFireAS0;
    private double _nextFireLS0;

    private int [] _data;
    private int _counter;

    private double _endTime;    
}
